home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 21 / AACD 21.iso / AACD / Utilities / Ghostscript / src / gdevcgml.c < prev    next >
Encoding:
C/C++ Source or Header  |  2001-01-01  |  28.2 KB  |  1,159 lines

  1. /* Copyright (C) 1995, 1996, 1998 Aladdin Enterprises.  All rights reserved.
  2.   
  3.   This file is part of AFPL Ghostscript.
  4.   
  5.   AFPL Ghostscript is distributed with NO WARRANTY OF ANY KIND.  No author or
  6.   distributor accepts any responsibility for the consequences of using it, or
  7.   for whether it serves any particular purpose or works at all, unless he or
  8.   she says so in writing.  Refer to the Aladdin Free Public License (the
  9.   "License") for full details.
  10.   
  11.   Every copy of AFPL Ghostscript must include a copy of the License, normally
  12.   in a plain ASCII text file named PUBLIC.  The License grants you the right
  13.   to copy, modify and redistribute AFPL Ghostscript, but only under certain
  14.   conditions described in the License.  Among other things, the License
  15.   requires that the copyright notice and this notice be preserved on all
  16.   copies.
  17. */
  18.  
  19. /*$Id: gdevcgml.c,v 1.2 2000/09/19 19:00:11 lpd Exp $ */
  20. /* CGM-writing library */
  21. #include "memory_.h"
  22. #include "stdio_.h"
  23. #include "gdevcgmx.h"
  24.  
  25. /* Forward references to command-writing procedures */
  26. private void begin_command(P2(cgm_state *, cgm_op_index));
  27.  
  28. #define OP(op) begin_command(st, op)
  29. private cgm_result end_command(P1(cgm_state *));
  30.  
  31. #define END_OP (void)end_command(st)
  32. #define DONE return end_command(st)
  33. /* Parameters */
  34. private void put_int(P3(cgm_state *, cgm_int, int));
  35.  
  36. #define CI(ci) put_int(st, ci, st->metafile.color_index_precision)
  37. #define I(i) put_int(st, i, st->metafile.integer_precision)
  38. #define IX(ix) put_int(st, ix, st->metafile.index_precision)
  39. #define E(e) put_int(st, (int)(e), 16)
  40. private void put_real(P3(cgm_state *, cgm_real, const cgm_precision *));
  41.  
  42. #define R(r) put_real(st, r, &st->metafile.real_precision)
  43. private void put_vdc(P2(cgm_state *, const cgm_vdc *));
  44.  
  45. #define VDC(vdc) put_vdc(st, vdc)
  46. #define VDC2(vdc1, vdc2) VDC(vdc1); VDC(vdc2)
  47. #define VDC4(vdc1, vdc2, vdc3, vdc4) VDC2(vdc1, vdc2); VDC2(vdc3, vdc4)
  48. private void put_vdc_r(P3(cgm_state *, const cgm_line_marker_extent *, cgm_line_marker_specification_mode));
  49.  
  50. #define VDC_R(vdcr, mode) put_vdc_r(st, vdcr, mode)
  51. private void put_point(P2(cgm_state *, const cgm_point *));
  52.  
  53. #define P(p) put_point(st, p)
  54. private void put_points(P3(cgm_state *, const cgm_point *, int));
  55.  
  56. #define nP(p, n) put_points(st, p, n)
  57. private void put_string(P3(cgm_state *, const char *, uint));
  58.  
  59. #define S(s, l) put_string(st, s, l)
  60. private void put_color(P2(cgm_state *, const cgm_color *));
  61.  
  62. #define CO(co) put_color(st, co)
  63. private void put_rgb(P2(cgm_state *, const cgm_rgb *));
  64.  
  65. #define CD(cd) put_rgb(st, cd)
  66. /* Other data types */
  67. #define put_byte(st, b)\
  68.   if ( st->command_count == command_max_count ) write_command(st, false);\
  69.   st->command[st->command_count++] = (byte)(b)
  70. private void put_bytes(P3(cgm_state *, const byte *, uint));
  71. private void write_command(P2(cgm_state *, bool));
  72. private void put_real_precision(P2(cgm_state *, const cgm_precision *));
  73.  
  74. /* ================ Public routines ================ */
  75.  
  76. /* ---------------- Initialize/terminate ---------------- */
  77.  
  78. /* Initialize a CGM writer. */
  79. cgm_state *
  80. cgm_initialize(FILE * file, const cgm_allocator * cal)
  81. {
  82.     cgm_state *st = (*cal->alloc) (cal->private_data, sizeof(cgm_state));
  83.  
  84.     if (st == 0)
  85.     return 0;
  86.     st->file = file;
  87.     st->allocator = *cal;
  88.     /* Initialize metafile elements. */
  89.     st->metafile.vdc_type = cgm_vdc_integer;
  90.     st->metafile.integer_precision = 16;
  91.     st->metafile.real_precision.representation = cgm_representation_fixed;
  92.     st->metafile.real_precision.exponent_or_whole_width = 16;
  93.     st->metafile.real_precision.fraction_width = 16;
  94.     st->metafile.index_precision = 16;
  95.     st->metafile.color_precision = 8;
  96.     st->metafile.color_index_precision = 8;
  97.     st->metafile.maximum_color_index = 63;
  98.     /* color_value_extent */
  99.     /*st->metafile.character_coding_announcer = 0; */
  100.     /* Initialize picture elements. */
  101.     st->picture.scaling_mode = cgm_scaling_abstract;
  102.     st->picture.color_selection_mode = cgm_color_selection_indexed;
  103.     st->picture.line_width_specification_mode = cgm_line_marker_absolute;
  104.     st->picture.marker_size_specification_mode = cgm_line_marker_absolute;
  105.     st->picture.edge_width_specification_mode = cgm_line_marker_absolute;
  106.     /* vdc_extent */
  107.     /* background_color */
  108.     /* Initialize control elements. */
  109.     st->vdc_integer_precision = st->metafile.integer_precision;
  110.     st->vdc_real_precision = st->metafile.real_precision;
  111.     st->transparency = cgm_transparency_on;
  112.     /* clip_rectangle */
  113.     st->clip_indicator = cgm_clip_on;
  114.     /* Initialize other state elements. */
  115.     st->line_bundle_index = 1;
  116.     st->line_type = cgm_line_solid;
  117.     /* line_width */
  118.     /* line_color */
  119.     st->marker_bundle_index = 1;
  120.     st->marker_type = cgm_marker_asterisk;
  121.     /* marker_size */
  122.     /* marker_color */
  123.     st->text_bundle_index = 1;
  124.     st->text_font_index = 1;
  125.     st->text_precision = cgm_text_precision_string;
  126.     st->character_expansion_factor = 1.0;
  127.     st->character_spacing = 0.0;
  128.     /* text_color */
  129.     /* character_height */
  130.     /* character_orientation */
  131.     st->text_path = cgm_text_path_right;
  132.     /* text_alignment */
  133.     st->character_set_index = 1;
  134.     st->alternate_character_set_index = 1;
  135.     st->fill_bundle_index = 1;
  136.     st->interior_style = cgm_interior_style_hollow;
  137.     st->hatch_index = cgm_hatch_horizontal;
  138.     st->pattern_index = 1;
  139.     st->edge_bundle_index = 1;
  140.     st->edge_type = cgm_edge_solid;
  141.     /* edge_width */
  142.     st->edge_visibility = false;
  143.     /* fill_reference_point */
  144.     /* pattern_table */
  145.     /* pattern_size */
  146.     /* color_table */
  147.     memset(st->source_flags, (byte) cgm_aspect_source_individual,
  148.        sizeof(st->source_flags));
  149.     return st;
  150. }
  151.  
  152. /* Terminate a CGM writer. */
  153. cgm_result
  154. cgm_terminate(cgm_state * st)
  155. {
  156.     (*st->allocator.free) (st->allocator.private_data, st);
  157.     return cgm_result_ok;
  158. }
  159.  
  160. /* ---------------- Metafile elements ---------------- */
  161.  
  162. cgm_result
  163. cgm_BEGIN_METAFILE(cgm_state * st, const char *str, uint len)
  164. {
  165.     OP(BEGIN_METAFILE);
  166.     S(str, len);
  167.     DONE;
  168. }
  169.  
  170. cgm_result
  171. cgm_set_metafile_elements(cgm_state * st, const cgm_metafile_elements * meta, long mask)
  172. {
  173.     if ((mask & cgm_set_METAFILE_VERSION)) {
  174.     OP(METAFILE_VERSION);
  175.     I(meta->metafile_version);
  176.     END_OP;
  177.     st->metafile.metafile_version = meta->metafile_version;
  178.     }
  179.     if ((mask & cgm_set_METAFILE_DESCRIPTION)) {
  180.     OP(METAFILE_DESCRIPTION);
  181.     S(meta->metafile_description.chars, meta->metafile_description.length);
  182.     END_OP;
  183.     st->metafile.metafile_description = meta->metafile_description;
  184.     }
  185.     if ((mask & cgm_set_VDC_TYPE)) {
  186.     OP(VDC_TYPE);
  187.     E(meta->vdc_type);
  188.     END_OP;
  189.     st->metafile.vdc_type = meta->vdc_type;
  190.     }
  191.     if ((mask & cgm_set_INTEGER_PRECISION)) {
  192.     OP(INTEGER_PRECISION);
  193.     I(meta->integer_precision);
  194.     END_OP;
  195.     st->metafile.integer_precision = meta->integer_precision;
  196.     }
  197.     if ((mask & cgm_set_REAL_PRECISION)) {
  198.     OP(REAL_PRECISION);
  199.     put_real_precision(st, &meta->real_precision);
  200.     END_OP;
  201.     st->metafile.real_precision = meta->real_precision;
  202.     }
  203.     if ((mask & cgm_set_INDEX_PRECISION)) {
  204.     OP(INDEX_PRECISION);
  205.     I(meta->index_precision);
  206.     END_OP;
  207.     st->metafile.index_precision = meta->index_precision;
  208.     }
  209.     if ((mask & cgm_set_COLOR_PRECISION)) {
  210.     OP(COLOR_PRECISION);
  211.     I(meta->color_precision);
  212.     END_OP;
  213.     st->metafile.color_index_precision = meta->color_index_precision;
  214.     }
  215.     if ((mask & cgm_set_COLOR_INDEX_PRECISION)) {
  216.     OP(COLOR_INDEX_PRECISION);
  217.     I(meta->color_index_precision);
  218.     END_OP;
  219.     st->metafile.color_index_precision = meta->color_index_precision;
  220.     }
  221.     if ((mask & cgm_set_MAXIMUM_COLOR_INDEX)) {
  222.     OP(MAXIMUM_COLOR_INDEX);
  223.     CI(meta->maximum_color_index);
  224.     END_OP;
  225.     st->metafile.maximum_color_index = meta->maximum_color_index;
  226.     }
  227.     if ((mask & cgm_set_METAFILE_ELEMENT_LIST)) {
  228.     int i;
  229.     const int *p;
  230.  
  231.     OP(METAFILE_ELEMENT_LIST);
  232.     for (i = 0, p = meta->metafile_element_list;
  233.          i < meta->metafile_element_list_count;
  234.          i++, p += 2
  235.         ) {
  236.         I(p[0]);
  237.         I(p[1]);
  238.     }
  239.     END_OP;
  240.     st->metafile.metafile_element_list =
  241.         meta->metafile_element_list;
  242.     st->metafile.metafile_element_list_count =
  243.         meta->metafile_element_list_count;
  244.     }
  245.     /* element list */
  246.     if ((mask & cgm_set_FONT_LIST)) {
  247.     int i;
  248.  
  249.     OP(FONT_LIST);
  250.     for (i = 0; i < meta->font_list_count; ++i)
  251.         S(meta->font_list[i].chars, meta->font_list[i].length);
  252.     END_OP;
  253.     st->metafile.font_list = meta->font_list;
  254.     st->metafile.font_list_count = meta->font_list_count;
  255.     }
  256.     /* character set list */
  257.     /* character coding announcer */
  258.     return st->result;
  259. }
  260.  
  261. cgm_result
  262. cgm_END_METAFILE(cgm_state * st)
  263. {
  264.     OP(END_METAFILE);
  265.     DONE;
  266. }
  267.  
  268. /* ---------------- Picture elements ---------------- */
  269.  
  270. cgm_result
  271. cgm_BEGIN_PICTURE(cgm_state * st, const char *str, uint len)
  272. {
  273.     OP(BEGIN_PICTURE);
  274.     S(str, len);
  275.     DONE;
  276. }
  277.  
  278. cgm_result
  279. cgm_set_picture_elements(cgm_state * st, const cgm_picture_elements * pic, long mask)
  280. {
  281.     if ((mask & cgm_set_SCALING_MODE)) {
  282.     OP(SCALING_MODE);
  283.     E(pic->scaling_mode);
  284.     R(pic->scale_factor);
  285.     st->picture.scaling_mode = pic->scaling_mode;
  286.     st->picture.scale_factor = pic->scale_factor;
  287.     END_OP;
  288.     }
  289.     if ((mask & cgm_set_COLOR_SELECTION_MODE)) {
  290.     OP(COLOR_SELECTION_MODE);
  291.     E(pic->color_selection_mode);
  292.     END_OP;
  293.     st->picture.color_selection_mode = pic->color_selection_mode;
  294.     }
  295.     if ((mask & cgm_set_LINE_WIDTH_SPECIFICATION_MODE)) {
  296.     OP(LINE_WIDTH_SPECIFICATION_MODE);
  297.     E(pic->line_width_specification_mode);
  298.     END_OP;
  299.     st->picture.line_width_specification_mode = pic->line_width_specification_mode;
  300.     }
  301.     if ((mask & cgm_set_MARKER_SIZE_SPECIFICATION_MODE)) {
  302.     OP(MARKER_SIZE_SPECIFICATION_MODE);
  303.     E(pic->marker_size_specification_mode);
  304.     END_OP;
  305.     st->picture.marker_size_specification_mode = pic->marker_size_specification_mode;
  306.     }
  307.     if ((mask & cgm_set_EDGE_WIDTH_SPECIFICATION_MODE)) {
  308.     OP(EDGE_WIDTH_SPECIFICATION_MODE);
  309.     E(pic->edge_width_specification_mode);
  310.     END_OP;
  311.     st->picture.edge_width_specification_mode = pic->edge_width_specification_mode;
  312.     }
  313.     if ((mask & cgm_set_VDC_EXTENT)) {
  314.     OP(VDC_EXTENT);
  315.     P(&pic->vdc_extent[0]);
  316.     P(&pic->vdc_extent[1]);
  317.     END_OP;
  318.     st->picture.vdc_extent[0] = pic->vdc_extent[0];
  319.     st->picture.vdc_extent[1] = pic->vdc_extent[1];
  320.     }
  321.     if ((mask & cgm_set_BACKGROUND_COLOR)) {
  322.     OP(BACKGROUND_COLOR);
  323.     CD(&pic->background_color.rgb);
  324.     DONE;
  325.     st->picture.background_color = pic->background_color;
  326.     }
  327.     return st->result;
  328. }
  329.  
  330. cgm_result
  331. cgm_BEGIN_PICTURE_BODY(cgm_state * st)
  332. {
  333.     OP(BEGIN_PICTURE_BODY);
  334.     DONE;
  335. }
  336.  
  337. cgm_result
  338. cgm_END_PICTURE(cgm_state * st)
  339. {
  340.     OP(END_PICTURE);
  341.     DONE;
  342. }
  343.  
  344. /* ---------------- Control elements ---------------- */
  345.  
  346. cgm_result
  347. cgm_VDC_INTEGER_PRECISION(cgm_state * st, int precision)
  348. {
  349.     if (st->vdc_integer_precision != precision) {
  350.     OP(VDC_INTEGER_PRECISION);
  351.     I(precision);
  352.     st->vdc_integer_precision = precision;
  353.     DONE;
  354.     } else
  355.     return cgm_result_ok;
  356. }
  357.  
  358. cgm_result
  359. cgm_VDC_REAL_PRECISION(cgm_state * st, const cgm_precision * precision)
  360. {
  361.     OP(VDC_REAL_PRECISION);
  362.     put_real_precision(st, precision);
  363.     st->vdc_real_precision = *precision;
  364.     DONE;
  365. }
  366.  
  367. cgm_result
  368. cgm_AUXILIARY_COLOR(cgm_state * st, const cgm_color * color)
  369. {
  370.     OP(AUXILIARY_COLOR);
  371.     CO(color);
  372.     st->auxiliary_color = *color;
  373.     DONE;
  374. }
  375.  
  376. cgm_result
  377. cgm_TRANSPARENCY(cgm_state * st, cgm_transparency transparency)
  378. {
  379.     OP(TRANSPARENCY);
  380.     E(transparency);
  381.     st->transparency = transparency;
  382.     DONE;
  383. }
  384.  
  385. cgm_result
  386. cgm_CLIP_RECTANGLE(cgm_state * st, const cgm_point rectangle[2])
  387. {
  388.     OP(CLIP_RECTANGLE);
  389.     P(&rectangle[0]);
  390.     st->clip_rectangle[0] = rectangle[0];
  391.     P(&rectangle[1]);
  392.     st->clip_rectangle[1] = rectangle[1];
  393.     DONE;
  394. }
  395.  
  396. cgm_result
  397. cgm_CLIP_INDICATOR(cgm_state * st, cgm_clip_indicator clip)
  398. {
  399.     OP(CLIP_INDICATOR);
  400.     E(clip);
  401.     st->clip_indicator = clip;
  402.     DONE;
  403. }
  404.  
  405. /* ---------------- Graphical primitive elements ---------------- */
  406.  
  407. cgm_result
  408. cgm_POLYLINE(cgm_state * st, const cgm_point * vertices, int count)
  409. {
  410.     OP(POLYLINE);
  411.     nP(vertices, count);
  412.     DONE;
  413. }
  414.  
  415. cgm_result
  416. cgm_DISJOINT_POLYLINE(cgm_state * st, const cgm_point * endpoints, int count)
  417. {
  418.     OP(DISJOINT_POLYLINE);
  419.     nP(endpoints, count);
  420.     DONE;
  421. }
  422.  
  423. cgm_result
  424. cgm_POLYMARKER(cgm_state * st, const cgm_point * positions, int count)
  425. {
  426.     OP(POLYMARKER);
  427.     nP(positions, count);
  428.     DONE;
  429. }
  430.  
  431. cgm_result
  432. cgm_TEXT(cgm_state * st, const cgm_point * position, bool final, const char *str, uint len)
  433. {
  434.     OP(TEXT);
  435.     P(position);
  436.     E(final);
  437.     S(str, len);
  438.     DONE;
  439. }
  440.  
  441. cgm_result
  442. cgm_RESTRICTED_TEXT(cgm_state * st, const cgm_vdc * delta_width, const cgm_vdc * delta_height, const cgm_point * position, bool final, const char *str, uint len)
  443. {
  444.     OP(RESTRICTED_TEXT);
  445.     VDC2(delta_width, delta_height);
  446.     P(position);
  447.     E(final);
  448.     S(str, len);
  449.     DONE;
  450. }
  451.  
  452. cgm_result
  453. cgm_APPEND_TEXT(cgm_state * st, bool final, const char *str, uint len)
  454. {
  455.     OP(APPEND_TEXT);
  456.     E(final);
  457.     S(str, len);
  458.     DONE;
  459. }
  460.  
  461. cgm_result
  462. cgm_POLYGON(cgm_state * st, const cgm_point * vertices, int count)
  463. {
  464.     OP(POLYGON);
  465.     nP(vertices, count);
  466.     DONE;
  467. }
  468.  
  469. cgm_result
  470. cgm_POLYGON_SET(cgm_state * st, const cgm_polygon_edge * vertices, int count)
  471. {
  472.     int i;
  473.  
  474.     OP(POLYGON);
  475.     for (i = 0; i < count; ++i) {
  476.     P(&vertices[i].vertex);
  477.     E(vertices[i].edge_out);
  478.     }
  479.     DONE;
  480. }
  481.  
  482. cgm_result
  483. cgm_CELL_ARRAY(cgm_state * st, const cgm_point * pqr /*[3] */ , cgm_int nx, cgm_int ny, cgm_int local_color_precision, cgm_cell_representation_mode mode, const byte * values, uint source_bit, uint raster)
  484. {
  485.     int precision = local_color_precision;
  486.     int bits_per_pixel;
  487.     uint row_bytes;
  488.     const byte *row = values + (source_bit >> 3);
  489.     int bit = source_bit & 7;
  490.     int y;
  491.  
  492.     /* Currently we ignore the cell representation_mode, and always */
  493.     /* produce cell arrays in 'packed' format. */
  494.     mode = cgm_cell_mode_packed;
  495.     OP(CELL_ARRAY);
  496.     nP(pqr, 3);
  497.     I(nx);
  498.     I(ny);
  499.     I(local_color_precision);
  500.     E(mode);
  501.     if (precision == 0)
  502.     precision = (st->picture.color_selection_mode ==
  503.              cgm_color_selection_indexed ?
  504.              st->metafile.color_index_precision :
  505.              st->metafile.color_precision);
  506.     bits_per_pixel =
  507.     (st->picture.color_selection_mode == cgm_color_selection_indexed ?
  508.      precision : precision * 3);
  509.     row_bytes = (bits_per_pixel * nx + 7) >> 3;
  510.     for (y = 0; y < ny; y++, row += raster) {
  511.     if (bit == 0)
  512.         put_bytes(st, row, row_bytes);
  513.     else {
  514.         uint i;
  515.  
  516.         for (i = 0; i < row_bytes; i++) {
  517.         byte b = (row[i] << bit) +
  518.         (row[i + 1] >> (8 - bit));
  519.  
  520.         put_byte(st, b);
  521.         }
  522.     }
  523.     if ((row_bytes & 1)) {
  524.         put_byte(st, 0);
  525.     }
  526.     }
  527.     DONE;
  528. }
  529.  
  530. cgm_result
  531. cgm_RECTANGLE(cgm_state * st, const cgm_point * corner1, const cgm_point * corner2)
  532. {
  533.     OP(RECTANGLE);
  534.     P(corner1);
  535.     P(corner2);
  536.     DONE;
  537. }
  538.  
  539. cgm_result
  540. cgm_CIRCLE(cgm_state * st, const cgm_point * center, const cgm_vdc * radius)
  541. {
  542.     OP(CIRCLE);
  543.     P(center);
  544.     VDC(radius);
  545.     DONE;
  546. }
  547.  
  548. cgm_result
  549. cgm_CIRCULAR_ARC_3_POINT(cgm_state * st, const cgm_point * start, const cgm_point * intermediate, const cgm_point * end)
  550. {
  551.     OP(CIRCULAR_ARC_3_POINT);
  552.     P(start);
  553.     P(intermediate);
  554.     P(end);
  555.     DONE;
  556. }
  557.  
  558. cgm_result
  559. cgm_CIRCULAR_ARC_3_POINT_CLOSE(cgm_state * st, const cgm_point * start, const cgm_point * intermediate, const cgm_point * end, cgm_arc_closure closure)
  560. {
  561.     OP(CIRCULAR_ARC_3_POINT_CLOSE);
  562.     P(start);
  563.     P(intermediate);
  564.     P(end);
  565.     E(closure);
  566.     DONE;
  567. }
  568.  
  569. cgm_result
  570. cgm_CIRCULAR_ARC_CENTER(cgm_state * st, const cgm_point * center, const cgm_vdc * dx_start, const cgm_vdc * dy_start, const cgm_vdc * dx_end, const cgm_vdc * dy_end, const cgm_vdc * radius)
  571. {
  572.     OP(CIRCULAR_ARC_CENTER);
  573.     P(center);
  574.     VDC4(dx_start, dy_start, dx_end, dy_end);
  575.     VDC(radius);
  576.     DONE;
  577. }
  578.  
  579. cgm_result
  580. cgm_CIRCULAR_ARC_CENTER_CLOSE(cgm_state * st, const cgm_point * center, const cgm_vdc * dx_start, const cgm_vdc * dy_start, const cgm_vdc * dx_end, const cgm_vdc * dy_end, const cgm_vdc * radius, cgm_arc_closure closure)
  581. {
  582.     OP(CIRCULAR_ARC_CENTER_CLOSE);
  583.     P(center);
  584.     VDC4(dx_start, dy_start, dx_end, dy_end);
  585.     VDC(radius);
  586.     E(closure);
  587.     DONE;
  588. }
  589.  
  590. cgm_result
  591. cgm_ELLIPSE(cgm_state * st, const cgm_point * center, const cgm_point * cd1_end, const cgm_point * cd2_end)
  592. {
  593.     OP(ELLIPSE);
  594.     P(center);
  595.     P(cd1_end);
  596.     P(cd2_end);
  597.     DONE;
  598. }
  599.  
  600. cgm_result
  601. cgm_ELLIPTICAL_ARC(cgm_state * st, const cgm_point * center, const cgm_point * cd1_end, const cgm_point * cd2_end, const cgm_vdc * dx_start, const cgm_vdc * dy_start, const cgm_vdc * dx_end, const cgm_vdc * dy_end)
  602. {
  603.     OP(ELLIPTICAL_ARC);
  604.     P(center);
  605.     P(cd1_end);
  606.     P(cd2_end);
  607.     VDC4(dx_start, dy_start, dx_end, dy_end);
  608.     DONE;
  609. }
  610.  
  611. cgm_result
  612. cgm_ELLIPTICAL_ARC_CLOSE(cgm_state * st, const cgm_point * center, const cgm_point * cd1_end, const cgm_point * cd2_end, const cgm_vdc * dx_start, const cgm_vdc * dy_start, const cgm_vdc * dx_end, const cgm_vdc * dy_end, cgm_arc_closure closure)
  613. {
  614.     OP(ELLIPTICAL_ARC_CLOSE);
  615.     P(center);
  616.     P(cd1_end);
  617.     P(cd2_end);
  618.     VDC4(dx_start, dy_start, dx_end, dy_end);
  619.     E(closure);
  620.     DONE;
  621. }
  622.  
  623. /* ---------------- Attribute elements ---------------- */
  624.  
  625. cgm_result
  626. cgm_LINE_BUNDLE_INDEX(cgm_state * st, cgm_int index)
  627. {
  628.     OP(LINE_BUNDLE_INDEX);
  629.     IX(index);
  630.     st->line_bundle_index = index;
  631.     DONE;
  632. }
  633.  
  634. cgm_result
  635. cgm_LINE_TYPE(cgm_state * st, cgm_line_type line_type)
  636. {
  637.     OP(LINE_TYPE);
  638.     IX((int)line_type);
  639.     st->line_type = line_type;
  640.     DONE;
  641. }
  642.  
  643. cgm_result
  644. cgm_LINE_WIDTH(cgm_state * st, const cgm_line_width * line_width)
  645. {
  646.     OP(LINE_WIDTH);
  647.     VDC_R(line_width, st->picture.line_width_specification_mode);
  648.     st->line_width = *line_width;
  649.     DONE;
  650. }
  651.  
  652. cgm_result
  653. cgm_LINE_COLOR(cgm_state * st, const cgm_color * color)
  654. {
  655.     OP(LINE_COLOR);
  656.     CO(color);
  657.     st->line_color = *color;
  658.     DONE;
  659. }
  660.  
  661. cgm_result
  662. cgm_MARKER_BUNDLE_INDEX(cgm_state * st, cgm_int index)
  663. {
  664.     OP(MARKER_BUNDLE_INDEX);
  665.     IX(index);
  666.     st->marker_bundle_index = index;
  667.     DONE;
  668. }
  669.  
  670. cgm_result
  671. cgm_MARKER_TYPE(cgm_state * st, cgm_marker_type marker_type)
  672. {
  673.     OP(MARKER_TYPE);
  674.     IX((int)marker_type);
  675.     st->marker_type = marker_type;
  676.     DONE;
  677. }
  678.  
  679. cgm_result
  680. cgm_MARKER_SIZE(cgm_state * st, const cgm_marker_size * marker_size)
  681. {
  682.     OP(MARKER_SIZE);
  683.     VDC_R(marker_size, st->picture.marker_size_specification_mode);
  684.     st->marker_size = *marker_size;
  685.     DONE;
  686. }
  687.  
  688. cgm_result
  689. cgm_MARKER_COLOR(cgm_state * st, const cgm_color * color)
  690. {
  691.     OP(MARKER_COLOR);
  692.     CO(color);
  693.     st->marker_color = *color;
  694.     DONE;
  695. }
  696.  
  697. cgm_result
  698. cgm_TEXT_BUNDLE_INDEX(cgm_state * st, cgm_int index)
  699. {
  700.     OP(TEXT_BUNDLE_INDEX);
  701.     IX(index);
  702.     st->text_bundle_index = index;
  703.     DONE;
  704. }
  705.  
  706. cgm_result
  707. cgm_TEXT_FONT_INDEX(cgm_state * st, cgm_int index)
  708. {
  709.     OP(TEXT_FONT_INDEX);
  710.     IX(index);
  711.     st->text_font_index = index;
  712.     DONE;
  713. }
  714.  
  715. cgm_result
  716. cgm_TEXT_PRECISION(cgm_state * st, cgm_text_precision precision)
  717. {
  718.     OP(TEXT_PRECISION);
  719.     E(precision);
  720.     st->text_precision = precision;
  721.     DONE;
  722. }
  723.  
  724. cgm_result
  725. cgm_CHARACTER_EXPANSION_FACTOR(cgm_state * st, cgm_real factor)
  726. {
  727.     OP(CHARACTER_EXPANSION_FACTOR);
  728.     R(factor);
  729.     st->character_expansion_factor = factor;
  730.     DONE;
  731. }
  732.  
  733. cgm_result
  734. cgm_CHARACTER_SPACING(cgm_state * st, cgm_real spacing)
  735. {
  736.     OP(CHARACTER_SPACING);
  737.     R(spacing);
  738.     st->character_spacing = spacing;
  739.     DONE;
  740. }
  741.  
  742. cgm_result
  743. cgm_TEXT_COLOR(cgm_state * st, const cgm_color * color)
  744. {
  745.     OP(TEXT_COLOR);
  746.     CO(color);
  747.     st->text_color = *color;
  748.     DONE;
  749. }
  750.  
  751. cgm_result
  752. cgm_CHARACTER_HEIGHT(cgm_state * st, const cgm_vdc * height)
  753. {
  754.     OP(CHARACTER_HEIGHT);
  755.     VDC(height);
  756.     st->character_height = *height;
  757.     DONE;
  758. }
  759.  
  760. cgm_result
  761. cgm_CHARACTER_ORIENTATION(cgm_state * st, const cgm_vdc * x_up, const cgm_vdc * y_up, const cgm_vdc * x_base, const cgm_vdc * y_base)
  762. {
  763.     OP(CHARACTER_ORIENTATION);
  764.     VDC4(x_up, y_up, x_base, y_base);
  765.     st->character_orientation[0] = *x_up;
  766.     st->character_orientation[1] = *y_up;
  767.     st->character_orientation[2] = *x_base;
  768.     st->character_orientation[3] = *y_base;
  769.     DONE;
  770. }
  771.  
  772. cgm_result
  773. cgm_TEXT_PATH(cgm_state * st, cgm_text_path text_path)
  774. {
  775.     OP(TEXT_PATH);
  776.     E(text_path);
  777.     st->text_path = text_path;
  778.     DONE;
  779. }
  780.  
  781. cgm_result
  782. cgm_TEXT_ALIGNMENT(cgm_state * st, cgm_text_alignment_horizontal align_h, cgm_text_alignment_vertical align_v, cgm_real align_cont_h, cgm_real align_cont_v)
  783. {
  784.     OP(TEXT_ALIGNMENT);
  785.     E(align_h);
  786.     E(align_v);
  787.     R(align_cont_h);
  788.     R(align_cont_v);
  789.     DONE;
  790. }
  791.  
  792. cgm_result
  793. cgm_CHARACTER_SET_INDEX(cgm_state * st, cgm_int index)
  794. {
  795.     OP(CHARACTER_SET_INDEX);
  796.     IX(index);
  797.     st->character_set_index = index;
  798.     DONE;
  799. }
  800.  
  801. /* See gdevcgml.c for why this isn't named cgm_ALTERNATE_.... */
  802. cgm_result
  803. cgm_ALT_CHARACTER_SET_INDEX(cgm_state * st, cgm_int index)
  804. {
  805.     OP(ALTERNATE_CHARACTER_SET_INDEX);
  806.     IX(index);
  807.     st->alternate_character_set_index = index;
  808.     DONE;
  809. }
  810.  
  811. cgm_result
  812. cgm_FILL_BUNDLE_INDEX(cgm_state * st, cgm_int index)
  813. {
  814.     OP(FILL_BUNDLE_INDEX);
  815.     IX(index);
  816.     st->fill_bundle_index = index;
  817.     DONE;
  818. }
  819.  
  820. cgm_result
  821. cgm_INTERIOR_STYLE(cgm_state * st, cgm_interior_style interior_style)
  822. {
  823.     OP(INTERIOR_STYLE);
  824.     E(interior_style);
  825.     st->interior_style = interior_style;
  826.     DONE;
  827. }
  828.  
  829. cgm_result
  830. cgm_FILL_COLOR(cgm_state * st, const cgm_color * color)
  831. {
  832.     OP(FILL_COLOR);
  833.     CO(color);
  834.     st->fill_color = *color;
  835.     DONE;
  836. }
  837.  
  838. cgm_result
  839. cgm_HATCH_INDEX(cgm_state * st, cgm_hatch_index hatch_index)
  840. {
  841.     OP(HATCH_INDEX);
  842.     IX((int)hatch_index);
  843.     st->hatch_index = hatch_index;
  844.     DONE;
  845. }
  846.  
  847. cgm_result
  848. cgm_PATTERN_INDEX(cgm_state * st, cgm_int index)
  849. {
  850.     OP(PATTERN_INDEX);
  851.     IX(index);
  852.     st->pattern_index = index;
  853.     DONE;
  854. }
  855.  
  856. cgm_result
  857. cgm_EDGE_BUNDLE_INDEX(cgm_state * st, cgm_int index)
  858. {
  859.     OP(EDGE_BUNDLE_INDEX);
  860.     IX(index);
  861.     st->edge_bundle_index = index;
  862.     DONE;
  863. }
  864.  
  865. cgm_result
  866. cgm_EDGE_TYPE(cgm_state * st, cgm_edge_type edge_type)
  867. {
  868.     OP(EDGE_TYPE);
  869.     IX((int)edge_type);
  870.     st->edge_type = edge_type;
  871.     DONE;
  872. }
  873.  
  874. cgm_result
  875. cgm_EDGE_WIDTH(cgm_state * st, const cgm_edge_width * edge_width)
  876. {
  877.     OP(EDGE_WIDTH);
  878.     VDC_R(edge_width, st->picture.edge_width_specification_mode);
  879.     st->edge_width = *edge_width;
  880.     DONE;
  881. }
  882.  
  883. cgm_result
  884. cgm_EDGE_COLOR(cgm_state * st, const cgm_color * color)
  885. {
  886.     OP(EDGE_COLOR);
  887.     CO(color);
  888.     DONE;
  889. }
  890.  
  891. cgm_result
  892. cgm_EDGE_VISIBILITY(cgm_state * st, bool visibility)
  893. {
  894.     OP(EDGE_VISIBILITY);
  895.     E(visibility);
  896.     st->edge_visibility = visibility;
  897.     DONE;
  898. }
  899.  
  900. cgm_result
  901. cgm_FILL_REFERENCE_POINT(cgm_state * st, const cgm_point * reference_point)
  902. {
  903.     OP(FILL_REFERENCE_POINT);
  904.     P(reference_point);
  905.     st->fill_reference_point = *reference_point;
  906.     DONE;
  907. }
  908.  
  909. /* PATTERN_TABLE */
  910.  
  911. cgm_result
  912. cgm_PATTERN_SIZE(cgm_state * st, const cgm_vdc * x_height, const cgm_vdc * y_height, const cgm_vdc * x_width, const cgm_vdc * y_width)
  913. {
  914.     OP(PATTERN_SIZE);
  915.     VDC4(x_height, y_height, x_width, y_width);
  916.     st->pattern_size[0] = *x_height;
  917.     st->pattern_size[1] = *y_height;
  918.     st->pattern_size[2] = *x_width;
  919.     st->pattern_size[3] = *y_width;
  920.     DONE;
  921. }
  922.  
  923. cgm_result
  924. cgm_COLOR_TABLE(cgm_state * st, cgm_int index, const cgm_color * values, int count)
  925. {
  926.     int i;
  927.  
  928.     OP(COLOR_TABLE);
  929.     CI(index);
  930.     for (i = 0; i < count; ++i)
  931.     CD(&values[i].rgb);
  932.     DONE;
  933. }
  934.  
  935. cgm_result 
  936. cgm_ASPECT_SOURCE_FLAGS(cgm_state * st, const cgm_aspect_source_flag * flags, int count)
  937. {
  938.     int i;
  939.  
  940.     OP(ASPECT_SOURCE_FLAGS);
  941.     for (i = 0; i < count; ++i) {
  942.     E(flags[i].type);
  943.     E(flags[i].source);
  944.     st->source_flags[flags[i].type] = (byte) flags[i].source;
  945.     }
  946.     DONE;
  947. }
  948.  
  949. /* ================ Internal routines ================ */
  950.  
  951. /* Begin a command. */
  952. private void
  953. begin_command(cgm_state * st, cgm_op_index op)
  954. {
  955.     uint op_word = (uint) op << cgm_op_id_shift;
  956.  
  957.     st->command[0] = (byte) (op_word >> 8);
  958.     st->command[1] = (byte) (op_word);
  959.     st->command_count = 4;    /* leave room for extension */
  960.     st->command_first = true;
  961.     st->result = cgm_result_ok;
  962. }
  963.  
  964. /* Write the buffer for a partial command. */
  965. /* Note that we always write an even number of bytes. */
  966. private void
  967. write_command(cgm_state * st, bool last)
  968. {
  969.     byte *command = st->command;
  970.     int count = st->command_count;
  971.  
  972.     if (st->command_first) {
  973.     if (count <= 34) {
  974.         command[2] = command[0];
  975.         command[3] = command[1] + count - 4;
  976.         command += 2, count -= 2;
  977.     } else {
  978.         int pcount = count - 4;
  979.  
  980.         command[1] |= 31;
  981.         command[2] = (byte) (pcount >> 8);
  982.         if (!last)
  983.         command[2] |= 0x80;
  984.         command[3] = (byte) pcount;
  985.     }
  986.     st->command_first = false;
  987.     } else {
  988.     int pcount = count - 2;
  989.  
  990.     command[0] = (byte) (pcount >> 8);
  991.     if (!last)
  992.         command[0] |= 0x80;
  993.     command[1] = (byte) pcount;
  994.     }
  995.     fwrite(command, sizeof(byte), count + (count & 1), st->file);
  996.     st->command_count = 2;    /* leave room for extension header */
  997.     if (ferror(st->file))
  998.     st->result = cgm_result_io_error;
  999. }
  1000.  
  1001. /* End a command. */
  1002. private cgm_result
  1003. end_command(cgm_state * st)
  1004. {
  1005.     write_command(st, true);
  1006.     return st->result;
  1007. }
  1008.  
  1009. /* Put an integer value. */
  1010. private void
  1011. put_int(cgm_state * st, cgm_int value, int precision)
  1012. {
  1013.     switch (precision) {
  1014.     case 32:
  1015.         put_byte(st, value >> 24);
  1016.     case 24:
  1017.         put_byte(st, value >> 16);
  1018.     case 16:
  1019.         put_byte(st, value >> 8);
  1020.     case 8:
  1021.         put_byte(st, value);
  1022.     }
  1023. }
  1024.  
  1025. /* Put a real value. */
  1026. private void
  1027. put_real(cgm_state * st, cgm_real value, const cgm_precision * pr)
  1028. {
  1029.     if (pr->representation == cgm_representation_floating) {
  1030.     } else {            /* Casting to integer simply discards the fraction, */
  1031.     /* so we need to be careful with negative values. */
  1032.     long whole = (long)value;
  1033.     double fpart;
  1034.  
  1035.     if (value < whole)
  1036.         --whole;
  1037.     fpart = value - whole;
  1038.     put_int(st, whole, pr->exponent_or_whole_width);
  1039.     if (pr->fraction_width == 16) {
  1040.         uint fraction = (uint) (fpart * (1.0 * 0x10000));
  1041.  
  1042.         put_int(st, fraction, 16);
  1043.     } else {        /* pr->fraction_width == 32 */
  1044.         ulong fraction =
  1045.         (ulong) (fpart * (1.0 * 0x10000 * 0x10000));
  1046.  
  1047.         put_int(st, fraction, 32);
  1048.     }
  1049.     }
  1050. }
  1051.  
  1052. /* Put a real precision. */
  1053. private void
  1054. put_real_precision(cgm_state * st, const cgm_precision * precision)
  1055. {
  1056.     I((int)precision->representation);
  1057.     I(precision->exponent_or_whole_width);
  1058.     I(precision->fraction_width);
  1059. }
  1060.  
  1061. /* Put a VDC. */
  1062. private void
  1063. put_vdc(cgm_state * st, const cgm_vdc * pvdc)
  1064. {
  1065.     if (st->metafile.vdc_type == cgm_vdc_integer)
  1066.     put_int(st, pvdc->integer, st->vdc_integer_precision);
  1067.     else
  1068.     put_real(st, pvdc->real, &st->vdc_real_precision);
  1069. }
  1070.  
  1071. /* Put a VDC or a real. */
  1072. private void
  1073. put_vdc_r(cgm_state * st, const cgm_line_marker_extent * extent,
  1074.       cgm_line_marker_specification_mode mode)
  1075. {
  1076.     if (mode == cgm_line_marker_absolute)
  1077.     VDC(&extent->absolute);
  1078.     else
  1079.     R(extent->scaled);
  1080. }
  1081.  
  1082. /* Put a point (pair of VDCs). */
  1083. private void
  1084. put_point(cgm_state * st, const cgm_point * ppt)
  1085. {
  1086.     if (st->metafile.vdc_type == cgm_vdc_integer) {
  1087.     put_int(st, ppt->integer.x, st->vdc_integer_precision);
  1088.     put_int(st, ppt->integer.y, st->vdc_integer_precision);
  1089.     } else {
  1090.     put_real(st, ppt->real.x, &st->vdc_real_precision);
  1091.     put_real(st, ppt->real.y, &st->vdc_real_precision);
  1092.     }
  1093. }
  1094.  
  1095. /* Put a list of points. */
  1096. private void
  1097. put_points(cgm_state * st, const cgm_point * ppt, int count)
  1098. {
  1099.     int i;
  1100.  
  1101.     for (i = 0; i < count; i++)
  1102.     P(ppt + i);
  1103. }
  1104.  
  1105. /* Put bytes. */
  1106. private void
  1107. put_bytes(cgm_state * st, const byte * data, uint length)
  1108. {
  1109.     int count;
  1110.  
  1111.     while (length > (count = command_max_count - st->command_count)) {
  1112.     memcpy(st->command + st->command_count, data, count);
  1113.     st->command_count += count;
  1114.     write_command(st, false);
  1115.     data += count;
  1116.     length -= count;
  1117.     }
  1118.     memcpy(st->command + st->command_count, data, length);
  1119.     st->command_count += length;
  1120. }
  1121.  
  1122. /* Put a string. */
  1123. private void
  1124. put_string(cgm_state * st, const char *data, uint length)
  1125. {                /* The CGM specification seems to imply that the continuation */
  1126.     /* mechanism for commands and the mechanism for strings */
  1127.     /* are orthogonal; we take this interpretation. */
  1128.     if (length >= 255) {
  1129.     put_byte(st, 255);
  1130.     while (length > 32767) {
  1131.         put_int(st, 65535, 2);
  1132.         put_bytes(st, (const byte *)data, 32767);
  1133.         data += 32767;
  1134.         length -= 32767;
  1135.     }
  1136.     }
  1137.     put_byte(st, length);
  1138.     put_bytes(st, (const byte *)data, length);
  1139. }
  1140.  
  1141. /* Put a color. */
  1142. private void
  1143. put_color(cgm_state * st, const cgm_color * color)
  1144. {
  1145.     if (st->picture.color_selection_mode == cgm_color_selection_indexed)
  1146.     CI(color->index);
  1147.     else
  1148.     CD(&color->rgb);
  1149. }
  1150.  
  1151. /* Put an RGB value. */
  1152. private void
  1153. put_rgb(cgm_state * st, const cgm_rgb * rgb)
  1154. {
  1155.     put_int(st, rgb->r, st->metafile.color_precision);
  1156.     put_int(st, rgb->g, st->metafile.color_precision);
  1157.     put_int(st, rgb->b, st->metafile.color_precision);
  1158. }
  1159.